package org.example.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.domain.dto.PageDTO;
import org.example.domain.po.ErpAccount;
import org.example.domain.po.ErpDepotHead;
import org.example.domain.query.report.*;
import org.example.domain.po.ErpDepot;
import org.example.domain.vo.report.account.AccountBillVO;
import org.example.domain.vo.report.account.BaseAccountHead;
import org.example.domain.vo.report.account.ErpAccountVO;
import org.example.domain.vo.report.account.detail.data.Payment;
import org.example.domain.vo.report.account.detail.data.Transfer;
import org.example.domain.vo.report.allocate.AllocateDepot;
import org.example.domain.vo.report.inDetail.Menyimpan;
import org.example.domain.vo.report.inOutStockReport.InOutStockReport;
import org.example.domain.vo.report.materialStock.ErpMaterialStockVO;
import org.example.domain.vo.report.ErpReport;
import org.example.domain.vo.report.materialStock.InventoryFlows;
import org.example.domain.vo.report.materialStock.billDetail.BaseInventory;
import org.example.domain.vo.report.materialStock.billDetail.data.SaleIn;
import org.example.domain.vo.report.retail.RetailStatistics;
import org.example.domain.vo.report.stock_warning.StockWarningReport;
import org.example.domain.vo.report.summary.StorageSummary;
import org.example.mapper.ErpReportMapper;
import org.example.service.*;
import org.example.utils.TableUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class ErpReportServiceImpl extends ServiceImpl<ErpReportMapper, ErpReport>
    implements ErpReportService {
    @Autowired
    private ErpDepotService erpDepotService;
    
    @Resource
    private ErpDepotHeadService depotHeadService;
    
    @Resource
    private ErpDepotHeadService erpDepotHeadService;

    @Resource
    private ErpAccountService erpAccountService;
    
    @Resource
    private ErpMaterialCategoryService erpMaterialCategoryService;
    
    @Resource
    private ErpAccountHeadService erpAccountHeadService;
    
    @Override
    public PageDTO<ErpMaterialStockVO> findMaterialStock(StockQuery stockQuery) {
        if (CollUtil.isEmpty(stockQuery.getDepotId())) {
            LambdaQueryWrapper<ErpDepot> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ErpDepot::getTenantId, stockQuery.getTenantId());
            
            List<ErpDepot> list = erpDepotService.list(wrapper);
            List<Long> depotIds = new ArrayList<>();
            list.forEach(item -> depotIds.add(item.getId()));
            stockQuery.setDepotId(depotIds);
        }
        Page<ErpReport> p = new Page<>(stockQuery.getCurrent(), stockQuery.getSize());
        Page<ErpMaterialStockVO> page =  baseMapper.findMaterialStock(p, stockQuery);
        return PageDTO.of(page, materialStock -> {
            ErpMaterialStockVO vo = BeanUtil.copyProperties(materialStock, ErpMaterialStockVO.class);
            int result = vo.getCurrentStock().compareTo(vo.getInitialInventory());
            if (result < 0){
                vo.setInventoryNumber(vo.getInitialInventory().subtract(vo.getCurrentStock()));
            }
            return vo;
        });
    }
    
    @Override
    public IPage<InventoryFlows> findMaterialBill(MaterialBillQuery materialBillQuery) {
        Page<ErpReport> page = new Page<>(materialBillQuery.getCurrent(), materialBillQuery.getSize());
        return baseMapper.findMaterialBill(page, materialBillQuery);
    }
    
    @Override
    public ErpDepotHead getDeportHeadByNumber(String headNumber) {
        LambdaQueryWrapper<ErpDepotHead> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ErpDepotHead::getNumber, headNumber);
        return erpDepotHeadService.getOne(wrapper);
    }
    
    @Override
    public BaseInventory getDetail(String number) {
        LambdaQueryWrapper<ErpDepotHead> headWrapper = new LambdaQueryWrapper<>();
        headWrapper.eq(ErpDepotHead::getNumber, number);
        ErpDepotHead depotHead = depotHeadService.getOne(headWrapper);
        
        // 具体类型
        String subType = depotHead.getSubType();
        if (depotHead.getType().equals("出库")){
            // 如果具体类型包含销售
            if (StrUtil.contains(subType, "销售")){
                SaleIn saleBillDetail = baseMapper.getSaleBillDetail(depotHead.getNumber());
                saleBillDetail.setSubType("销售出库");
                saleBillDetail.setTableTitle(TableUtil.getSaleTableTitle());
                return saleBillDetail;
            } else if (StrUtil.contains(subType, "零售")){
                // 零售出库
                SaleIn retailIn = baseMapper.getRetailDetail(depotHead.getNumber());
                retailIn.setTableTitle(TableUtil.getRetailOrderTableTitle());
                return retailIn;
            } else if (StrUtil.contains(subType, "采购")){
                SaleIn saleBack = baseMapper.getSaleBillDetail(depotHead.getNumber());
                saleBack.setTableTitle(TableUtil.getSaleTableTitle());
                return saleBack;
            } else if (StrUtil.contains(subType, "其它") || StrUtil.contains(subType, "调拨")){
                // 其它出库
                SaleIn retailIn = baseMapper.getRetailDetail(depotHead.getNumber());
                retailIn.setTableTitle(TableUtil.getRetailOrderTableTitle());
                return retailIn;
            }
        } else if (depotHead.getType().equals("入库")){
            if (StrUtil.contains(subType, "销售退货")){
                SaleIn saleBack = baseMapper.getSaleBillDetail(depotHead.getNumber());
                saleBack.setSubType("销售退货");
                saleBack.setTableTitle(TableUtil.getSaleTableTitle());
                return saleBack;
            } else if (StrUtil.contains(subType, "采购")){
                SaleIn purchaseDetail = baseMapper.getSaleBillDetail(depotHead.getNumber());
                purchaseDetail.setTableTitle(TableUtil.getSaleTableTitle());
                return purchaseDetail;
            } else if (StrUtil.contains(subType, "零售退货")){
                SaleIn retailIn = baseMapper.getRetailDetail(depotHead.getNumber());
                retailIn.setTableTitle(TableUtil.getRetailOrderTableTitle());
                return retailIn;
            } else if (StrUtil.contains(subType, "其它")){
                // 其它入库
                SaleIn retailIn = baseMapper.getRetailDetail(depotHead.getNumber());
                retailIn.setTableTitle(TableUtil.getRetailOrderTableTitle());
                return retailIn;
            }
        } else if (depotHead.getType().equals("其它")){
            if (StrUtil.contains(subType, "销售订单")){
                // 查询销售订单
                SaleIn saleBillDetail = baseMapper.getSaleBillDetail(depotHead.getNumber());
                saleBillDetail.setSubType("销售订单");
                saleBillDetail.setTableTitle(TableUtil.getSaleOrderTableTitle());
                return saleBillDetail;
            } else if (StrUtil.contains(subType, "采购订单")){
                // 查询采购订单
                SaleIn saleBillDetail = baseMapper.getSaleBillDetail(depotHead.getNumber());
                saleBillDetail.setSubType("采购订单");
                saleBillDetail.setTableTitle(TableUtil.getSaleOrderTableTitle());
                return saleBillDetail;
            }
        }
        return null;
    }

    @Override
    public IPage<ErpAccountVO> pageFindAccount(AccQuery accQuery) {
        Page<ErpReport> page = new Page<>(accQuery.getCurrent(), accQuery.getSize());
        return baseMapper.pageFindAccount(page, accQuery);
    }

    @Override
    public List<AccountBillVO> findAccountBill(Long accId, Long tenantId) {
        ErpAccount account = erpAccountService.getById(accId);
        // 初始金额
        AtomicReference<BigDecimal> initialAmount = new AtomicReference<>(account.getInitialAmount());

        List<AccountBillVO> accountBill = baseMapper.findAccountBill(accId, tenantId);
        // 根据订单时间升序后集合
        List<AccountBillVO> accountBillTwo = accountBill.stream().sorted(Comparator.comparing(AccountBillVO::getOperTime)).collect(Collectors.toList());
        accountBillTwo.forEach(item -> {
            initialAmount.updateAndGet(value -> value.add(item.getChangeAmount()));
            item.setCurrentAmount(initialAmount.get());
        });
        // 降序
        accountBillTwo.sort(Comparator.comparing(AccountBillVO::getOperTime).reversed());
        return accountBillTwo;
    }
    
    
    @Override
    public BaseAccountHead getAccountHeadDetail(Long tenantId, String headNumber, String subType) {
        if (subType.equals("付款") || subType.equals("收款")){
            Payment payment = baseMapper.getAccountHeadDetail1(tenantId, headNumber);
            return payment;
        } else {
            // 转账、收入、支出、收预付款
            Transfer transfer = baseMapper.getAccountHeadDetail2(tenantId, headNumber);
            return transfer;
        }
    }
    
    @Override
    public IPage<RetailStatistics> findRetailStatistics(RetailStatisticsQuery query) {
        Page<RetailStatistics> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.findRetailStatistics(page, query);
    }
    
    @Override
    public IPage<RetailStatistics> findPurchaseStatistics(RetailStatisticsQuery query) {
        Page<RetailStatistics> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.findPurchaseStatistics(page, query);
    }
    
    @Override
    public IPage<RetailStatistics> findSaleStatistics(RetailStatisticsQuery query) {
        Page<RetailStatistics> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.findSaleStatistics(page, query);
    }
    
    @Override
    public IPage<Menyimpan> findMenyimpanPage(InDetailQuery inDetailQuery) {
        Page<Menyimpan> page = new Page<>(inDetailQuery.getCurrent(), inDetailQuery.getSize());
        return baseMapper.findMenyimpanPage(page, inDetailQuery);
    }
    
    @Override
    public IPage<StorageSummary> findStorageSummaryPage(StorageSummaryQuery query) {
        Page<StorageSummary> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.findStorageSummaryPage(page, query);
    }
    
    @Override
    public IPage<AllocateDepot> findAllocateDepotPage(AllocateDepotQuery query) {
        Page<AllocateDepot> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.findAllocateDepotPage(page, query);
    }
    
    @Override
    public IPage<InOutStockReport> findInOutStockReportPage(InOutStockReportQuery query) {
        Page<InOutStockReport> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<InOutStockReport> inOutStockReportPage = baseMapper.findInOutStockReportPage(page, query);
        List<InOutStockReport> records = inOutStockReportPage.getRecords();
        records.forEach(item -> item.setMoney(item.getMonthNumber().multiply(item.getPurchaseDecimal())));
        return inOutStockReportPage;
    }
    
    @Override
    public IPage<StockWarningReport> findStockWarning(InOutStockReportQuery query) {
        Page<StockWarningReport> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.findStockWarning(page, query);
    }
}
